home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 013 / autopark.arc / AUTOPARK.ASM next >
Encoding:
Assembly Source File  |  1986-05-03  |  21.1 KB  |  447 lines

  1.               PAGE           66,132
  2. VECTORS       SEGMENT        AT 0H 
  3.               ORG            8H*4
  4. TOD_VECTOR    LABEL          DWORD     ; CLOCK INTERRUPT
  5.               ORG            13H*4
  6. DISK_VECTOR   LABEL          DWORD     ; HARD DISK BIOS CALL
  7. VECTORS       ENDS
  8. ;
  9. ; THIS IS THE START OF THE LOCAL DATA AND EXECUTABLE CODE
  10. ;
  11. CODE_SEG      SEGMENT
  12.               ASSUME         CS:CODE_SEG
  13.               ORG            100H
  14. BEGIN:        CALL           PARK      ; FIND OUT WHERE TO PARK
  15.               JMP            INIT_VECTORS ;INITIALIZE VECTORS & ATTACH TO DOS
  16. ROM_TOD_INT   DD             ?         ; ADDRESSES FOR ROM ROUTINES
  17. ROM_DISK_INT  DD             ?
  18. TIMER_DELAY   DW             546       ; DELAY BEFORE PARKING HEAD
  19. DELAY         DW             ?         ; CLOCK TICKS DURING DELAY
  20. BUSY          DB             0
  21. CYLNUM0       DW             0
  22. CYLNUM1       DW             0
  23. ;
  24. ; PARK THE HARD DISK HEAD AFTER DELAY WITHOUT USE
  25. ;
  26. ;
  27. OUR_TOD_INT   PROC           NEAR
  28.               PUSHF
  29.               CALL           ROM_TOD_INT ; GO TO OTHER CODE FIRST
  30.               PUSH           AX
  31.               PUSH           DS
  32.               MOV            AX,CS     ; SET DATA SEGMENT TO OURSELF
  33.               MOV            DS,AX
  34.               ASSUME         DS:CODE_SEG
  35.               DEC            DELAY     ; HAS DELAY ELAPSED?
  36.               JZ             PARK_IT   ; YUP
  37.               JG             COUNT_DOWN ; NOPE
  38.               MOV            DELAY,0   ; HEAD IS PARKED, RESET COUNTER TO 0
  39. COUNT_DOWN:   POP            DS
  40.               POP            AX
  41.               ASSUME         DS:NOTHING
  42.               IRET
  43. PARK_IT:      ASSUME         DS:CODE_SEG
  44.               PUSH           AX
  45.               PUSH           BX
  46.               PUSH           CX
  47.               PUSH           DX
  48.               TEST           BUSY,80H            ; IS DISK CODE BUSY?
  49.               JNZ            IT_IS_BUSY          ; OOPS, YES
  50.               CMP            CYLNUM0,0           ; IS THERE A DISK 0?
  51.               JE             NODISK0             ; NOPE
  52.               MOV            AH,0CH              ; SEEK
  53.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  54.               MOV            DL,80H              ; DRIVE 0
  55.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  56.               MOV            CX,CYLNUM0          ; GET CYL NUMBER
  57.               XCHG           CL,CH               ; PUT LO ORDER IN CH
  58.               SAL            CL,1                ; PUT HI IN TOP OF CL
  59.               SAL            CL,1                ; PUT HI IN TOP OF CL
  60.               SAL            CL,1                ; PUT HI IN TOP OF CL
  61.               SAL            CL,1                ; PUT HI IN TOP OF CL
  62.               SAL            CL,1                ; PUT HI IN TOP OF CL
  63.               SAL            CL,1                ; PUT HI IN TOP OF CL
  64.               INC            CL                  ; NOW SAY SECTOR 1
  65.               PUSHF
  66.               CALL           ROM_DISK_INT        ; MUST USE CALL SINCE INT 13H > HERE
  67. NODISK0:
  68.               CMP            CYLNUM1,0           ; IS THERE A DISK 1?
  69.               JE             NODISK1             ; NO
  70.               MOV            AH,0CH              ; SEEK
  71.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  72.               MOV            DL,81H              ; DRIVE 1
  73.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  74.               MOV            CX,CYLNUM1          ; GET CYL NUMBER
  75.               XCHG           CL,CH               ; PUT LO ORDER IN CH
  76.               SAL            CL,1                ; PUT HI IN TOP OF CL
  77.               SAL            CL,1                ; PUT HI IN TOP OF CL
  78.               SAL            CL,1                ; PUT HI IN TOP OF CL
  79.               SAL            CL,1                ; PUT HI IN TOP OF CL
  80.               SAL            CL,1                ; PUT HI IN TOP OF CL
  81.               SAL            CL,1                ; PUT HI IN TOP OF CL
  82.               INC            CL                  ; NOW SAY SECTOR 1
  83.               PUSHF
  84.               CALL           ROM_DISK_INT        ; MUST USE CALL SINCE INT 13H > HERE
  85. NODISK1:
  86.               POP            DX
  87.               POP            CX
  88.               POP            BX
  89.               POP            AX
  90.               JMP            COUNT_DOWN
  91. IT_IS_BUSY:   CALL           RESET               ; DISK IS BUSY, WAIT ANOTHER 5 SEC
  92.               POP            DX
  93.               POP            CX
  94.               POP            BX
  95.               POP            AX
  96.               JMP            COUNT_DOWN
  97. OUR_TOD_INT   ENDP
  98. ;
  99. ; THIS PROCEDURE RESETS THE TIMER COUNT TO ITS INITIAL VALUE
  100. ;
  101. RESET         PROC           NEAR
  102.               PUSH           AX
  103.               PUSH           DS 
  104.               MOV            AX,CS
  105.               MOV            DS,AX
  106.               ASSUME         DS:CODE_SEG
  107.               MOV            AX,TIMER_DELAY
  108.               MOV            DELAY,AX
  109.               POP            DS
  110.               POP            AX
  111.               RET
  112. RESET         ENDP
  113. ;
  114. ;
  115. ; THIS PROCEDURE RESETS THE TIME-OUT COUNTER AND PASSES CONTROL
  116. ; TO THE BIOS DISK ROUTINES
  117. ;
  118. CATCH_DISK    PROC           FAR
  119.               ASSUME         DS:NOTHING
  120.               OR             BUSY,80H  ; MARK DISK BUSY
  121.               TEST           DL,80H    ; IS IT A HARD DISK CALL?
  122.               JZ             NORESET   ; NO
  123.               CALL           RESET     ; RESET THE TIME-OUT COUNTER
  124. NORESET:      PUSHF                    ; SIMULATE INTERRUPT
  125.               CALL           ROM_DISK_INT ; DO BIOS STUFF
  126.               PUSHF                    ; REMEMBER FLAGS FROM DISK ROUTINE
  127.               AND            BUSY,7FH  ; MARK DISK NOT BUSY
  128.               POPF                     ; REMEMBER FLAGS FROM DISK ROUTINE
  129.               RET            2         ; THROW AWAY USER'S SAVED FLAGS
  130. CATCH_DISK    ENDP
  131. ;
  132. ; THIS PROCEDURE INITIALIZES THE INTERRUPT VECTORS
  133. ;
  134. INIT_VECTORS  PROC           NEAR
  135.               ASSUME         DS:VECTORS
  136.               MOV            AX,VECTORS ; SET UP DATA SEGMENT FOR VECTORS
  137.               MOV            DS,AX
  138.               CLI
  139.               MOV            AX,WORD PTR TOD_VECTOR ; SAVE ADDRESSES OF BIOS ROUTINES
  140.               MOV            WORD PTR ROM_TOD_INT,AX
  141.               MOV            AX,WORD PTR TOD_VECTOR[2]
  142.               MOV            WORD PTR ROM_TOD_INT[2],AX
  143.               MOV            WORD PTR TOD_VECTOR,OFFSET OUR_TOD_INT
  144.               MOV            WORD PTR TOD_VECTOR[2],CS
  145.               MOV            AX,WORD PTR DISK_VECTOR
  146.               MOV            WORD PTR ROM_DISK_INT,AX
  147.               MOV            AX,WORD PTR DISK_VECTOR[2]
  148.               MOV            WORD PTR ROM_DISK_INT[2],AX
  149.               MOV            WORD PTR DISK_VECTOR,OFFSET CATCH_DISK
  150.               MOV            WORD PTR DISK_VECTOR[2],CS
  151.               MOV            AX,TIMER_DELAY ; SET DELAY TO STARTING COUNT
  152.               MOV            DELAY,AX
  153.               STI                      ; ALLOW INTERRUPTS AGAIN
  154.               MOV            DX,OFFSET INIT_VECTORS ; END OF RESIDENT PORTION
  155.               INT            27H       ; TERMINATE BUT STAY RESIDENT
  156. INIT_VECTORS  ENDP
  157.               SUBTTL         PARK -- PARK THE HEADS IN ORDER TO FIND OUT WHERE TO PARK
  158.               PAGE
  159. PARK          PROC
  160.               PUSH           AX
  161.               PUSH           CX
  162.               PUSH           DX
  163.               PUSH           ES
  164. ;
  165. ;  MOVE DRIVE 0 AS FAR AS POSSIBLE IN STEPS OF 100 TRACKS
  166. ;
  167. SEEK0100:     MOV            AH,0CH              ; SEEK
  168.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  169.               MOV            DL,80H              ; DRIVE 0
  170.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  171.               MOV            CX,CYLNUM0          ; GET CYLINDER NUMBER
  172.               ADD            CX,100              ; INCREMENT BY 100
  173.               MOV            CYLNUM0,CX          ; PUT IT BACK
  174.               XCHG           CL,CH               ; PUT LO ORDER IN CH
  175.               SAL            CL,1                ; PUT HI IN TOP OF CL
  176.               SAL            CL,1                ; PUT HI IN TOP OF CL
  177.               SAL            CL,1                ; PUT HI IN TOP OF CL
  178.               SAL            CL,1                ; PUT HI IN TOP OF CL
  179.               SAL            CL,1                ; PUT HI IN TOP OF CL
  180.               SAL            CL,1                ; PUT HI IN TOP OF CL
  181.               INC            CL                  ; NOW SAY SECTOR 1
  182.               INT            13H
  183.               MOV            AH,01H              ; CHECK STATUS
  184.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  185.               MOV            DL,80H              ; DRIVE 0
  186.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  187.               MOV            CX,1                ; CYL 0 SECTOR 1
  188.               INT            13H
  189.               OR             AL,AL
  190.               JZ             SEEK0100
  191.               MOV            AX,CYLNUM0
  192.               SUB            AX,100
  193.               MOV            CYLNUM0,AX
  194. ;
  195. ;  MOVE DRIVE 0 AS FAR AS POSSIBLE IN STEPS OF 10 TRACKS
  196. ;
  197. SEEK010:      MOV            AH,0CH              ; SEEK
  198.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  199.               MOV            DL,80H              ; DRIVE 0
  200.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  201.               MOV            CX,CYLNUM0          ; GET CYLINDER NUMBER
  202.               ADD            CX,10               ; INCREMENT BY 10
  203.               MOV            CYLNUM0,CX          ; PUT IT BACK
  204.               XCHG           CL,CH               ; PUT LO ORDER IN CH
  205.               SAL            CL,1                ; PUT HI IN TOP OF CL
  206.               SAL            CL,1                ; PUT HI IN TOP OF CL
  207.               SAL            CL,1                ; PUT HI IN TOP OF CL
  208.               SAL            CL,1                ; PUT HI IN TOP OF CL
  209.               SAL            CL,1                ; PUT HI IN TOP OF CL
  210.               SAL            CL,1                ; PUT HI IN TOP OF CL
  211.               INC            CL                  ; NOW SAY SECTOR 1
  212.               INT            13H
  213.               MOV            AH,01H              ; CHECK STATUS
  214.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  215.               MOV            DL,80H              ; DRIVE 0
  216.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  217.               MOV            CX,1                ; CYL 0 SECTOR 1
  218.               INT            13H
  219.               OR             AL,AL
  220.               JZ             SEEK010
  221.               MOV            AX,CYLNUM0
  222.               SUB            AX,10
  223.               MOV            CYLNUM0,AX
  224. ;
  225. ;  MOVE DRIVE 0 AS FAR AS POSSIBLE IN STEPS OF 1 TRACK
  226. ;
  227. SEEK01:       MOV            AH,0CH              ; SEEK
  228.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  229.               MOV            DL,80H              ; DRIVE 0
  230.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  231.               INC            CYLNUM0             ; INCREMENT CYLINDER NUM
  232.               MOV            CX,CYLNUM0          ; GET CYL NUMBER
  233.               XCHG           CL,CH               ; PUT LO ORDER IN CH
  234.               SAL            CL,1                ; PUT HI IN TOP OF CL
  235.               SAL            CL,1                ; PUT HI IN TOP OF CL
  236.               SAL            CL,1                ; PUT HI IN TOP OF CL
  237.               SAL            CL,1                ; PUT HI IN TOP OF CL
  238.               SAL            CL,1                ; PUT HI IN TOP OF CL
  239.               SAL            CL,1                ; PUT HI IN TOP OF CL
  240.               INC            CL                  ; NOW SAY SECTOR 1
  241.               INT            13H
  242.               MOV            AH,01H              ; CHECK STATUS
  243.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  244.               MOV            DL,80H              ; DRIVE 0
  245.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  246.               MOV            CX,1                ; CYL 0 SECTOR 1
  247.               INT            13H
  248.               OR             AL,AL
  249.               JZ             SEEK01
  250.               DEC            CYLNUM0
  251.               CMP            CYLNUM0,0
  252.               JE             NODRIVE0
  253.               MOV            AX,CYLNUM0
  254.               PUSH           DS
  255.               POP            ES
  256.               LEA            DX,CYLDEC0
  257.               CALL           DECIMAL_CONVERT
  258.               MOV            AH,9
  259.               LEA            DX,CYLMSG0
  260.               INT            21H
  261. NODRIVE0:
  262. ;
  263. ;  MOVE DRIVE 1 AS FAR AS POSSIBLE IN STEPS OF 100 TRACKS
  264. ;
  265. SEEK1100:     MOV            AH,0CH              ; SEEK
  266.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  267.               MOV            DL,81H              ; DRIVE 1
  268.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  269.               MOV            CX,CYLNUM1          ; GET CYLINDER NUMBER
  270.               ADD            CX,100              ; INCREMENT BY 100
  271.               MOV            CYLNUM1,CX          ; PUT IT BACK
  272.               XCHG           CL,CH               ; PUT LO ORDER IN CH
  273.               SAL            CL,1                ; PUT HI IN TOP OF CL
  274.               SAL            CL,1                ; PUT HI IN TOP OF CL
  275.               SAL            CL,1                ; PUT HI IN TOP OF CL
  276.               SAL            CL,1                ; PUT HI IN TOP OF CL
  277.               SAL            CL,1                ; PUT HI IN TOP OF CL
  278.               SAL            CL,1                ; PUT HI IN TOP OF CL
  279.               INC            CL                  ; NOW SAY SECTOR 1
  280.               INT            13H
  281.               MOV            AH,01H              ; CHECK STATUS
  282.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  283.               MOV            DL,81H              ; DRIVE 1
  284.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  285.               MOV            CX,1                ; CYL 0 SECTOR 1
  286.               INT            13H
  287.               OR             AL,AL
  288.               JZ             SEEK1100
  289.               MOV            AX,CYLNUM1
  290.               SUB            AX,100
  291.               MOV            CYLNUM1,AX
  292. ;
  293. ;  MOVE DRIVE 1 AS FAR AS POSSIBLE IN STEPS OF 10 TRACKS
  294. ;
  295. SEEK110:      MOV            AH,0CH              ; SEEK
  296.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  297.               MOV            DL,81H              ; DRIVE 1
  298.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  299.               MOV            CX,CYLNUM1          ; GET CYLINDER NUMBER
  300.               ADD            CX,10               ; INCREMENT BY 10
  301.               MOV            CYLNUM1,CX          ; PUT IT BACK
  302.               XCHG           CL,CH               ; PUT LO ORDER IN CH
  303.               SAL            CL,1                ; PUT HI IN TOP OF CL
  304.               SAL            CL,1                ; PUT HI IN TOP OF CL
  305.               SAL            CL,1                ; PUT HI IN TOP OF CL
  306.               SAL            CL,1                ; PUT HI IN TOP OF CL
  307.               SAL            CL,1                ; PUT HI IN TOP OF CL
  308.               SAL            CL,1                ; PUT HI IN TOP OF CL
  309.               INC            CL                  ; NOW SAY SECTOR 1
  310.               INT            13H
  311.               MOV            AH,01H              ; CHECK STATUS
  312.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  313.               MOV            DL,81H              ; DRIVE 1
  314.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  315.               MOV            CX,1                ; CYL 0 SECTOR 1
  316.               INT            13H
  317.               OR             AL,AL
  318.               JZ             SEEK110
  319.               MOV            AX,CYLNUM1
  320.               SUB            AX,10
  321.               MOV            CYLNUM1,AX
  322. ;
  323. ;  MOVE DRIVE 0 AS FAR AS POSSIBLE IN STEPS OF 1 TRACK
  324. ;
  325. SEEK1:        MOV            AH,0CH              ; SEEK
  326.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  327.               MOV            DL,81H              ; DRIVE 1
  328.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  329.               INC            CYLNUM1             ; INCREMENT CYLINDER NUM
  330.               MOV            CX,CYLNUM1          ; GET CYL NUMBER
  331.               XCHG           CL,CH               ; PUT LO ORDER IN CH
  332.               SAL            CL,1                ; PUT HI IN TOP OF CL
  333.               SAL            CL,1                ; PUT HI IN TOP OF CL
  334.               SAL            CL,1                ; PUT HI IN TOP OF CL
  335.               SAL            CL,1                ; PUT HI IN TOP OF CL
  336.               SAL            CL,1                ; PUT HI IN TOP OF CL
  337.               SAL            CL,1                ; PUT HI IN TOP OF CL
  338.               INC            CL                  ; NOW SAY SECTOR 1
  339.               INT            13H
  340.               MOV            AH,01H              ; CHECK STATUS
  341.               MOV            AL,1                ; GOTTA HAVE A SECTOR COUNT
  342.               MOV            DL,81H              ; DRIVE 1
  343.               MOV            DH,0                ; GOTTA HAVE A HEAD NUMBER
  344.               MOV            CX,1                ; CYL 0 SECTOR 1
  345.               INT            13H
  346.               OR             AL,AL
  347.               JZ             SEEK1
  348.               DEC            CYLNUM1
  349.               CMP            CYLNUM1,0
  350.               JE             NODRIVE1
  351.               MOV            AX,CYLNUM1
  352.               PUSH           DS
  353.               POP            ES
  354.               LEA            DX,CYLDEC1
  355.               CALL           DECIMAL_CONVERT
  356.               MOV            AH,9
  357.               LEA            DX,CYLMSG1
  358.               INT            21H
  359. NODRIVE1:
  360.               MOV            AH,9
  361.               LEA            DX,BLANKLINE
  362.               INT            21H
  363.               POP            ES
  364.               POP            DX
  365.               POP            CX
  366.               POP            AX
  367.               RET
  368. CYLMSG0       DB             0AH,0DH,"Hard disk 0 parking place is cylinder"
  369. CYLDEC0       DB             "     .$"
  370. CYLMSG1       DB             0AH,0DH,"Hard disk 1 parking place is cylinder"
  371. CYLDEC1       DB             "     .$"
  372. BLANKLINE     DB             0AH,0DH,"$"
  373. PARK          ENDP
  374.               SUBTTL         DECIMAL CONVERT (TO ASCII STRING FOR DISPLAY)
  375.               PAGE
  376. ;
  377. ;  DECIMAL_CONVERT IS ENTERED WITH A NUMBER IN AX AND ES:DX POINTING TO
  378. ;  A FIVE-BYTE FIELD.  IT CONVERTS THE NUMBER INTO A FIVE-BYTE INTEGER
  379. ;  FROM 0 TO 65535 AND PLACES IT IN ASCII IN THE FIVE-BYTE FIELD.
  380. ;  IT ALTERS NO REGISTERS AT ALL.
  381. ;
  382. DECIMAL_CONVERT PROC
  383.               PUSH           BX
  384.               PUSH           DX
  385.               PUSH           DI
  386.               ASSUME         ES:NOTHING
  387. ;
  388. ;  DIVIDE BY TEN TO GET UNITS AS REMAINDER
  389. ;
  390.               MOV            DI,DX
  391.               MOV            BX,10               ; DIVISOR
  392.               MOV            DX,0                ; HIGH ORDER MUST BE ZERO
  393.               DIV            BX                  ; DIVIDE -- REMAINDER IN DX
  394.               ADD            DL,"0"              ; MAKE REMAINDER ASCII
  395.               MOV            BYTE PTR ES:[DI+4],DL  ; PUT BYTE IN DESTINATION
  396. ;
  397. ;  DIVIDE AGAIN FOR TENS
  398. ;
  399.               MOV            DX,0                ; HIGH ORDER MUST BE ZERO
  400.               DIV            BX
  401.               ADD            DL,"0"
  402.               MOV            BYTE PTR ES:[DI+3],DL
  403. ;
  404. ;  DIVIDE AGAIN FOR HUNDREDS
  405. ;
  406.               MOV            DX,0
  407.               DIV            BX
  408.               ADD            DL,"0"
  409.               MOV            BYTE PTR ES:[DI+2],DL
  410. ;
  411. ;  THOUSANDS
  412. ;
  413.               MOV            DX,0
  414.               DIV            BX
  415.               ADD            DL,"0"
  416.               MOV            BYTE PTR ES:[DI+1],DL
  417. ;
  418. ;  TEN-THOUSANDS
  419. ;
  420.               MOV            DX,0
  421.               DIV            BX
  422.               ADD            DL,"0"
  423.               MOV            BYTE PTR ES:[DI],DL
  424. ;
  425. ;  GET RID OF LEADING ZEROS
  426. ;
  427.               CMP            BYTE PTR ES:[DI],"0"
  428.               JNE            DECIMAL_DONE
  429.               MOV            BYTE PTR ES:[DI]," "
  430.               CMP            BYTE PTR ES:[DI+1],"0"
  431.               JNE            DECIMAL_DONE
  432.               MOV            BYTE PTR ES:[DI+1]," "
  433.               CMP            BYTE PTR ES:[DI+2],"0"
  434.               JNE            DECIMAL_DONE
  435.               MOV            BYTE PTR ES:[DI+2]," "
  436.               CMP            BYTE PTR ES:[DI+3],"0"
  437.               JNE            DECIMAL_DONE
  438.               MOV            BYTE PTR ES:[DI+3]," "
  439. DECIMAL_DONE:
  440.               POP            DI
  441.               POP            DX
  442.               POP            BX
  443.               RET
  444. DECIMAL_CONVERT ENDP
  445. CODE_SEG      ENDS
  446.               END            BEGIN
  447.